Skip to content

wasm32 and wasm64: default library borrow facts, -mm=gc refused, a JS host and test runs - #811

Merged
ASDAlexander77 merged 2 commits into
mainfrom
wasm-defaultlib
Nov 11, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
wasm-defaultlib

Conversation

@ASDAlexander77

@ASDAlexander77 ASDAlexander77 commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

wasm32 and wasm64 programs, linked with the default library and tested under Node. Goes with ASDAlexander77/TypeScriptCompilerDefaultLib#92, which builds the wasm default library.

Compiler

  • Own borrow facts from a wasm archive (ObjDumper.cpp): a wasm data symbol is an offset into its data segment, but it was read at that offset into the whole DATA section, whose contents start with the segment headers. An -mm=own program linked with the wasm default library therefore got none of the library's borrow facts and failed to compile.
  • An override of another arity (MLIRGenStore.h, MLIRGenClasses.cpp): an override such as get(scale?) of an abstract get(), or foo() of foo(x, y, ...z), was stored in the base method's vtable slot unchanged. Native code tolerates that; wasm's call_indirect checks the signature and traps. Now, as in C++, the override gets a slot of its own type. Each inherited slot holds a thunk of the slot's type, which passes undefined for a missing optional parameter and an empty array for a missing rest parameter, and drops extra arguments. New test: 00class_override_arity.
  • -mm=gc refused for wasm: gc is tslang's default, so a wasm executable or library now has to name another memory model. The error says so: the collector has no wasm build. Before, the link failed on a default-library folder that is never built.

Host and test runs (docs/how/wasm/test)

  • host.mjs: the imports a wasm program takes from env, which on other targets come from the C library and the default library's wrappers:
    • printf-family formatting, strtod/strtol, a heap
    • regex (JS RegExp), time and strftime
    • stdio and stdin
    • process and fs under Node
    • pointers and size_t as BigInt on wasm64
  • run.mjs runs one program under Node; index.html runs a folder of programs in a browser with the same host.
  • run_tests.mjs runs two suites for wasm32 and wasm64 under none, rc and own, in release (--opt) or debug (--debug):
    • tester: the tester's single-file ctest tests, built --no-default-lib as test-runner builds them. A test passes on done. and exit code 0.
    • defaultlib: the default library's tests, linked with the wasm default library. A test passes on ALL DONE, an empty stderr and exit code 0.
  • wasm64 needs Node 24 or later, because LLVM emits table64.

Results (Node 26, release and debug)

  • tester: 569 (wasm32) and 570 (wasm64) pass under none and rc, 0 fail. Under own, 419 pass and 0 fail; another 148–149 tests do not compile natively under own either.
  • defaultlib: 181 pass under none and rc, 180 under own, 0 fail, on both triples.
  • Native ctest: 6964/6964.

Skipped, and still open

Each skip is listed with its reason:

  • try/catch (64 tests): there are no landing pads on wasm yet, so a throw ends the program.
  • async: there is no async runtime for wasm.
  • threads.

wasm_skips.txt lists the open wasm compiler gaps:

  • 00object_func2: a method stored in an object's field is called as a function with this plus the object, but it takes only this. call_indirect checks the signature, so the call traps.
  • wasm32: the interface accessor-cell tag addr + 0x80000000 is folded into an i32.const, and wasm-ld fails with "LEB is outside Varint32 range".
  • wasm64: wasm-ld fails with "invalid data relocation" for a generator's next.
  • path.ts: a Readonly<Path> field read through Maybe<...> comes back wrong, and the loop never ends.

Also seen: 00owned_iteration failed once in a full wasm64 debug run. It then passed three times on its own.

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits November 11, 2026 18:21
…, a JS host and test runs

- ObjDumper: a wasm data symbol is an offset into its data segment, but it was read
  at that offset into the whole DATA section (segment headers first), so an own
  program linked with a wasm default library got none of its borrow facts and failed
  to compile.
- -mm=gc (the default) for a wasm executable or library is an error that says so:
  the collector has no wasm build. It used to fail on a default library folder that
  is never built.
- docs/how/wasm/test: host.mjs implements what a wasm program imports from `env`
  (the C library, the default library's wrappers: printf, strtod, malloc, regex, time,
  stdio, process/fs under Node), for Node (run.mjs) and the browser (index.html).
  run_tests.mjs compiles and runs the tester's single-file tests (--no-default-lib, as
  test-runner) and the default library's tests (linked with the wasm default library)
  for wasm32 and wasm64 under none, rc and own. Skipped, each with its reason: try/catch
  (does not catch on wasm yet), async, threads, and wasm_skips.txt, which lists the
  wasm compiler gaps still open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…slots call it through an adapter

A method overriding one with other parameters (get(scale?) for an abstract get(), foo() for
foo(x, y, ...z)) was stored in the base method's slot as it was. Native code tolerates the
mismatch, but wasm's call_indirect checks the signature and traps. Now, as in C++, the override
gets a slot of its own type, and each inherited slot holds a thunk of that slot's type: it passes
undefined for a missing optional parameter, an empty array for a missing rest parameter, and drops
extra arguments. 00function_overloads and callWithSpread now run on wasm32 and wasm64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 2baf05e into main Nov 11, 2026
8 checks passed
@ASDAlexander77
ASDAlexander77 deleted the wasm-defaultlib branch November 11, 2026 19:06
ASDAlexander77 added a commit that referenced this pull request Nov 12, 2026
…'s tests

PR #829's run booted the emulator and passed everything but two tester
tests, 00class_override_arity and 00optional_union_truthiness, under every
model: both came after v0.0-pre-alpha124 with the compiler fixes they check
(#811, #815). When the job takes a published release's package, it now takes
that release's tslang/test/tester/tests and CMakeLists.txt too; the runner
and its skips stay the commit's own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ASDAlexander77 added a commit that referenced this pull request Nov 12, 2026
…829)

* Android emulator tests: make the AVD where the emulator looks for it

Release run 43251862764's emulator exited at once: "Unknown AVD name
[tslang_api29_x86_64] ... no file tslang_api29_x86_64.ini in
$HOME/.android/avd". The runner's avdmanager had made it elsewhere. The run
job sets ANDROID_USER_HOME and ANDROID_AVD_HOME for both, and the install
step checks that `emulator -list-avds` names the AVD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Android emulator tests: a published package runs with its own release's tests

PR #829's run booted the emulator and passed everything but two tester
tests, 00class_override_arity and 00optional_union_truthiness, under every
model: both came after v0.0-pre-alpha124 with the compiler fixes they check
(#811, #815). When the job takes a published release's package, it now takes
that release's tslang/test/tester/tests and CMakeLists.txt too; the runner
and its skips stay the commit's own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant